﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using WeMakeSP.Platform.SharePoint.Lists;
using System.Text;

namespace WeMakeSP.ImageResizer
{
    /// <summary>
    /// A job that resize a specific image.
    /// </summary>
    public class ImageResizerJob : SPJobDefinition
    {
        #region Fields

        /// <summary>
        /// The list id.
        /// </summary>
        [Persisted]
        private Guid listId;

        /// <summary>
        /// The item id.
        /// </summary>
        [Persisted]
        private Guid itemId;

        /// <summary>
        /// The site id.
        /// </summary>
        [Persisted]
        private Guid siteId;

        /// <summary>
        /// The web id.
        /// </summary>
        [Persisted]
        private Guid webId;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ImageResizerJob"/> class.
        /// </summary>
        public ImageResizerJob()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ImageResizerJob"/> class.
        /// </summary>
        /// <param name="webApp">The web app.</param>
        public ImageResizerJob(SPWebApplication webApp) :
            base(null, webApp, null, SPJobLockType.None)
        {
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Adds the image.
        /// </summary>
        /// <param name="siteId">The site id.</param>
        /// <param name="webId">The web id.</param>
        /// <param name="listId">The list id.</param>
        /// <param name="itemId">The item id.</param>
        public void AddImage(Guid siteId, Guid webId, Guid listId, Guid itemId)
        {
            this.siteId = siteId;
            this.webId = webId;
            this.listId = listId;
            this.itemId = itemId;
        }

        /// <summary>
        /// Executes the job definition.
        /// </summary>
        /// <param name="targetInstanceId">For target types of <see cref="T:Microsoft.SharePoint.Administration.SPContentDatabase"></see> this is the database ID of the content database being processed by the running job. This value is Guid.Empty for all other target types.</param>
        public override void Execute(Guid targetInstanceId)
        {
            using (SPSite site = new SPSite(this.siteId))
            {
                using (SPWeb web = site.OpenWeb(this.webId))
                {
                    this.ResizeImage(web);
                }
            }
        }

        /// <summary>
        /// Submits the job.
        /// </summary>
        public void SubmitJob()
        {
            this.SubmitJobInternal(DateTime.Now);
        }
        
        /// <summary>
        /// Submits the job.
        /// </summary>
        /// <param name="hoursDelay">The hours delay.</param>
        /// <param name="minutesDelay">The minutes delay.</param>
        /// <param name="secondsDelay">The seconds delay.</param>
        public void SubmitJob(int hoursDelay, int minutesDelay, int secondsDelay)
        {
            if (hoursDelay < 0)
            {
                throw new ArgumentOutOfRangeException("hoursDelay");
            }

            if (minutesDelay < 0)
            {
                throw new ArgumentOutOfRangeException("minutesDelay");
            }

            if (secondsDelay < 0)
            {
                throw new ArgumentOutOfRangeException("secondsDelay");
            }

            DateTime jobStart = DateTime.Now;

            // Add the hours.

            jobStart = jobStart.AddHours(hoursDelay);

            // Add the minutes.

            jobStart = jobStart.AddMinutes(minutesDelay);

            // Add the seconds.

            jobStart = jobStart.AddSeconds(secondsDelay);

            // Submit the job.

            this.SubmitJobInternal(jobStart);
        }

        /// <summary>
        /// Submits the job.
        /// </summary>
        /// <param name="minutesDelay">The minutes delay.</param>
        /// <param name="secondsDelay">The seconds delay.</param>
        public void SubmitJob(int minutesDelay, int secondsDelay)
        {
            this.SubmitJob(0, minutesDelay, secondsDelay);
        }

        /// <summary>
        /// Submits the job.
        /// </summary>
        /// <param name="secondsDelay">The seconds delay.</param>
        public void SubmitJob(int secondsDelay)
        {
            this.SubmitJob(0, 0, secondsDelay);
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Resizes the image.
        /// </summary>
        /// <param name="web">The SharePoint web.</param>
        private void ResizeImage(SPWeb web)
        {
            // Enable unsafe updates.

            web.AllowUnsafeUpdates = true;

            SPList list =
                web.Lists[this.listId];
            
            SPListItem item =
                list.GetSafeItemByUniqueId(this.itemId);

            // Check if the item still exists.

            if (item != null)
            {
                ImageUploadPolicy imageUploadPolicy =
                    new ImageUploadPolicy(web, item);

                // Apply the policies to the item.

                imageUploadPolicy.ApplyPolicies();
            }

            // Disable unsafe updates.

            web.AllowUnsafeUpdates = false;
        }

        /// <summary>
        /// Submits the job internal.
        /// </summary>
        /// <param name="jobStart">The job start.</param>
        private void SubmitJobInternal(DateTime jobStart)
        {
            StringBuilder titleBuilder = 
                new StringBuilder();

            titleBuilder.Append("Image Resizer ");
            titleBuilder.Append("ListId:");
            titleBuilder.Append(this.listId);
            titleBuilder.Append(" ");
            titleBuilder.Append("ItemId:");
            titleBuilder.Append(this.itemId);

            this.Title = titleBuilder.ToString();
            this.Retry = false;
            this.Schedule = new SPOneTimeSchedule(jobStart);

            this.Update();
        }

        #endregion
    }
}
